﻿using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http.Filters;
using Newtonsoft.Json;
using SDCloudSolution.SDCloud.WebApi.Entities;
using SDCloudSolution.SDCloud.WebApi.Exceptions;

namespace SDCloudSolution.SDCloud.WebApi.Filters
{
    /// <summary>
    /// Handle exceptions that throws from rest api requests.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class WebApiExceptionHandlerFilter : ExceptionFilterAttribute
    {
        private JsonSerializer _jsonSerializer;

        private JsonSerializer JsonSerializer
        {
            get { return _jsonSerializer ?? (_jsonSerializer = new JsonSerializer()); }
        }

        private string Serialize(object data)
        {
            var stringWriter = new StringWriter();
            var jsonWriter = new JsonTextWriter(stringWriter);

            JsonSerializer.Serialize(jsonWriter, data);

            return stringWriter.ToString();
        }

        /// <summary>
        /// Raises the exception event.
        /// </summary>
        /// <param name="actionExecutedContext">The context for the action.</param>
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var response = new HttpResponseMessage();
            ErrorRestModel errorObject;

            var exception = actionExecutedContext.Exception;

            var apiException = exception as BaseSDCloudWebApiException;
            if (apiException != null)
            {
                response.StatusCode = apiException.StatusCode;
                errorObject = apiException.ToViewModel();
            }
            else
            {
                response.StatusCode = HttpStatusCode.InternalServerError;
                errorObject = new ErrorRestModel
                {
                    Message = "Error occurred"
                };

                // TODO Write handled exception to log
            }

            response.Content = new StringContent(Serialize(errorObject), Encoding.UTF8, "application/json");
            actionExecutedContext.Response = response;
        }
    }
}